package com.eipv.multidatasource.component.task;

import com.alibaba.fastjson.JSONObject;
import com.eipv.multidatasource.component.cache.QueueCache;
import com.eipv.multidatasource.component.cache.TableCache;
import com.eipv.multidatasource.controller.WebSocketServerController;
import com.eipv.multidatasource.entity.Column;
import com.eipv.multidatasource.entity.SingleMonitor;
import com.eipv.multidatasource.entity.Table;
import com.eipv.multidatasource.entity.TotalMonitor;
import com.eipv.multidatasource.mapper.mysql.MysqlTableMapper;
import com.eipv.multidatasource.util.SpringUtils;

import java.io.File;
import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicLong;

public class ReadAndLoadInDbTask implements Runnable {
    private File file;

    private String tableName;

    private AtomicLong total;

    private long start;

    public ReadAndLoadInDbTask(File file, String tableName, AtomicLong total, long start) {
        this.file = file;
        this.tableName = tableName;
        this.total = total;
        this.start = start;
    }

    @Override
    public void run() {
        TotalMonitor totalMonitor = new TotalMonitor();
        SingleMonitor singleMonitor = new SingleMonitor();
        singleMonitor.setTableName(this.tableName);
        Table table = TableCache.TABLE_HANDLED.get(this.tableName);
        long localStart = System.currentTimeMillis();


        try {
            String filePath = file.getAbsolutePath();
            if (filePath.contains("\\")) {
                filePath = filePath.replaceAll("\\\\", "/");
            }
            if (table.getForeignTableName() != null && !TableCache.FINISHED_TABLES.containsKey(table.getForeignTableName())) {
                QueueCache.FILE_QUEUE.put(this.file);
                return;
            }

            MysqlTableMapper mysqlTableMapper = SpringUtils.getBean(MysqlTableMapper.class);

            StringBuilder col = new StringBuilder();
            col.append("(");
            List<Column> columns = TableCache.COLUMNS.get(tableName);

            for (Column c : columns) {
                col.append("`").append(c.getColumnName()).append("`").append(",");
            }
            col = col.replace(col.lastIndexOf(","), col.length(), "");
            col.append(")");

            StringBuilder sql = new StringBuilder();

            sql.append("load data infile ")
                    .append("'").append(filePath).append("'")
                    .append("replace into table ")
                    .append("`").append(this.tableName).append("` ")
                    .append("fields terminated by ';' lines terminated by '\\n' ")
                    .append("IGNORE 1 LINES ")
                    .append(col).append(";");
            mysqlTableMapper.loadInDb(sql.toString());

            file.delete();
            long sum = Long.parseLong(file.getName().substring(file.getName().indexOf("-") + 1, file.getName().indexOf(".")));
            table.updateWriteRows(sum);
            table.updateTransferTime(System.currentTimeMillis() - localStart);

            if (table.isFinished()) {
                TableCache.TABLES_OF_PROCESSING.remove(table);
                TableCache.TABLES_OF_COMPLETED.add(table);

                singleMonitor.setStatus(SingleMonitor.FINISHED);

            } else {
                singleMonitor.setStatus(SingleMonitor.PROCESSING);
            }

            totalMonitor.setTables(TableCache.TABLES_OF_NEED_MIGRATE.size());
            totalMonitor.setCompleted(TableCache.TABLES_OF_COMPLETED.size());
            totalMonitor.setProcessing(TableCache.TABLES_OF_PROCESSING.size());
            totalMonitor.setFailed(TableCache.TABLES_OF_FAILED.size());
            totalMonitor.setVolume(TableCache.volume.get());
            long waste = System.currentTimeMillis() - start;
            totalMonitor.setTransferTime(new BigDecimal(waste).divide(new BigDecimal(1000), 3, BigDecimal.ROUND_CEILING));

            BigDecimal speedOfSize = new BigDecimal(TableCache.volume.get()).divide(new BigDecimal(waste).divide(new BigDecimal(1000)), 3, BigDecimal.ROUND_CEILING);
            totalMonitor.setSpeedOfSize(speedOfSize);

            BigDecimal speedOfRows = new BigDecimal((TableCache.rowsOfRead.get() + TableCache.rowsOfWrite.get()) / 2).divide(new BigDecimal(waste).divide(new BigDecimal(1000)), 0, BigDecimal.ROUND_CEILING);
            totalMonitor.setSpeedOfRows(speedOfRows);


            singleMonitor.setFileName(file.getAbsolutePath());
            singleMonitor.setRowsOfRead(table.getRowsOfRead());
            singleMonitor.setRowsOfWrite(table.getRowsOfWrite());
            singleMonitor.setTransferred(table.getTransferred());
            singleMonitor.setTransferTime(table.getTransferTime());
        } catch (Exception e) {
            singleMonitor.setException(e.getLocalizedMessage());
            singleMonitor.setStatus(SingleMonitor.FAILED);

            TableCache.TABLES_OF_PROCESSING.remove(table);
            TableCache.TABLES_OF_FAILED.add(table);
        } finally {
            long waste = System.currentTimeMillis() - start;
            totalMonitor.setTransferTime(new BigDecimal(waste).divide(new BigDecimal(1000), 3, BigDecimal.ROUND_CEILING));
            try {
                QueueCache.MONITOR_QUEUE.put(totalMonitor);
                QueueCache.MONITOR_QUEUE.put(singleMonitor);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}
